package utils;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

public class ImageUtil {
    private static Logger logger = LoggerFactory.getLogger(ImageUtil.class);

    /**
     * 通过图片base64流判断图片等于多少字节
     * image 图片流
     */
    public static Integer imageSize(String image) {
        // String str=image.substring(22); // 1.需要计算文件流大小，首先把头部的data:image/png;base64,（注意有逗号）去掉。
        String str = image;
        if (image.indexOf("data:image/png;base64,") > 0) {
            str = image.substring(22);
        }
        Integer equalIndex = str.indexOf("=");//2.找到等号，把等号也去掉
        if (str.indexOf("=") > 0) {
            str = str.substring(0, equalIndex);
        }
        Integer strLength = str.length();//3.原来的字符流大小，单位为字节
        Integer size = strLength - (strLength / 8) * 2;//4.计算后得到的文件流大小，单位为字节
        return size;
    }

    /**
     * 根据指定大小压缩图片
     *
     * @param imageBytes  源图片字节数组
     * @param desFileSize 指定图片大小，单位kb
     * @param imageId     影像编号
     * @return 压缩质量后的图片字节数组
     */
    public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize, String imageId) {
        if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) {
            return imageBytes;
        }
        long srcSize = imageBytes.length;
        double accuracy = getAccuracy(srcSize / 1024);
        try {
            while (imageBytes.length > desFileSize * 1024) {
                ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
                Thumbnails.of(inputStream)
                        .scale(accuracy)
                        .outputQuality(accuracy)
                        .toOutputStream(outputStream);
                imageBytes = outputStream.toByteArray();
            }
            logger.info("【图片压缩】imageId={} | 图片原大小={}kb | 压缩后大小={}kb",
                    imageId, srcSize / 1024, imageBytes.length / 1024);
        } catch (Exception e) {
            logger.error("【图片压缩】msg=图片压缩失败!", e);
        }
        return imageBytes;
    }

    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 900) {
            accuracy = 0.85;
        } else if (size < 2047) {
            accuracy = 0.6;
        } else if (size < 3275) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }

    /**
     * 压缩图片到指定大小
     * @param imgbase64Str 图片base64
     * @param size 单位kb
     * @return
     */
    public static String getZipBase64Str(String imgbase64Str,int size) {
        BASE64Decoder decoder = new BASE64Decoder();
        String s = "";
        try {
            byte[] b = decoder.decodeBuffer(imgbase64Str);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {// 调整异常数据
                    b[i] += 256;
                }
            }
            b = compressPicForScale(b, size, "x");
            s=Base64.encodeBase64String(b);
        } catch (Exception e) {
            e.getMessage();
        }
        return s;
    }

    /**
     * 添加水印
     * @param inputStream
     * @param path
     * @return
     * @throws IOException
     */
    public static byte[] addWatermark(ByteArrayInputStream inputStream,String path) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        //watermark(位置，水印图，透明度)
//        Thumbnails.of(inputStream)
//                .size(1280, 1024)
//                .watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File("images/X.jpg")), 0.5f)
//                .outputQuality(0.8f)
//                .toFile(path);

        Thumbnails.of(inputStream)
                .size(1280, 1024)
                .watermark(Positions.CENTER, ImageIO.read(new File("images/X.jpg")), 0.5f)
                .outputQuality(0.8f)
                .toOutputStream(outputStream);
        return outputStream.toByteArray();
    }

    /**
     * 裁切
     * @return
     * @throws IOException
     */
    public static byte[] crop(ByteArrayInputStream inputStream,Positions positions) throws IOException {
        //sourceRegion()
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        //图片中心400*400的区域
        Thumbnails.of(inputStream)
                .sourceRegion(positions, 400,400)
                .size(200, 200)
                .keepAspectRatio(false)
                .toOutputStream(outputStream);


        return outputStream.toByteArray();
    }
}